View Javadoc

1   /***
2    * Copyright 2003-2004 Fabrizio Giustina.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.maven.xhtml;
17  
18  import java.io.File;
19  import java.io.IOException;
20  
21  import org.apache.tools.ant.Project;
22  import org.dom4j.Element;
23  import org.dom4j.io.XMLWriter;
24  import org.dom4j.tree.DefaultElement;
25  import org.xml.sax.EntityResolver;
26  import org.xml.sax.ErrorHandler;
27  import org.xml.sax.InputSource;
28  import org.xml.sax.SAXException;
29  import org.xml.sax.SAXParseException;
30  
31  /***
32   * ValidatorHandler.
33   * @author fgiust
34   * @version $Revision: 1.4 $ ($Author: fgiust $)
35   */
36  class ValidatorHandler implements ErrorHandler, EntityResolver
37  {
38  
39      /***
40       * number of errors found in the current file.
41       */
42      private int errorsFound;
43  
44      /***
45       * out.
46       */
47      private XMLWriter out;
48  
49      /***
50       * real EntityResolver for DTDs
51       */
52      private EntityResolver chainedEntityResolver;
53  
54      /***
55       * @return Returns the chainedEntityResolver.
56       */
57      public EntityResolver getChainedEntityResolver()
58      {
59          return this.chainedEntityResolver;
60      }
61  
62      /***
63       * @param chainedEntityResolver The chainedEntityResolver to set.
64       */
65      public void setChainedEntityResolver(EntityResolver chainedEntityResolver)
66      {
67          this.chainedEntityResolver = chainedEntityResolver;
68      }
69  
70      /***
71       * set XMLWriter for output.
72       * @param writer XMLWriter
73       */
74      public void setOut(XMLWriter writer)
75      {
76          this.out = writer;
77      }
78  
79      /***
80       * init the validation handler: set up current file and reset errors number.
81       * @param file File currently validated
82       */
83      public void init(File file)
84      {
85          this.errorsFound = 0;
86      }
87  
88      /***
89       * how many errors happened during last parsing?
90       * @return int number of errors
91       */
92      public int getErrors()
93      {
94          return this.errorsFound;
95      }
96  
97      /***
98       * an error occurred: increment errors count and log exception message.
99       * @param exception SAXParseException
100      */
101     public void error(SAXParseException exception)
102     {
103         this.errorsFound++;
104         doLog(exception, Project.MSG_ERR);
105     }
106 
107     /***
108      * a fatal error occurred: redirect to error().
109      * @param exception SAXParseException
110      */
111     public final void fatalError(SAXParseException exception)
112     {
113         error(exception);
114     }
115 
116     /***
117      * a warning occurred: redirect to error().
118      * @param exception SAXParseException
119      */
120     public final void warning(SAXParseException exception)
121     {
122         error(exception);
123     }
124 
125     /***
126      * log event to output.
127      * @param e SAXParseException
128      * @param logLevel int
129      */
130     private void doLog(SAXParseException e, int logLevel)
131     {
132         Element error = new DefaultElement("error");
133         error.addAttribute("line", "" + e.getLineNumber());
134         error.addAttribute("col", "" + e.getColumnNumber());
135         error.addAttribute("position", e.getLineNumber() + ":" + e.getColumnNumber());
136         error.addAttribute("level", "" + logLevel);
137 
138         String message = e.getMessage();
139         // check for invalid sequence ]]> and encode to be sure not to break the build
140         int endCdata;
141         while (message != null && (endCdata = message.indexOf("]]>")) > -1)
142         {
143             message = message.substring(0, endCdata) + "] ] >" + message.substring(endCdata + 3, message.length());
144         }
145 
146         error.addCDATA(message);
147         writeToLog(error);
148     }
149 
150     /***
151      * this method is not used to resolve entities, but to log dtd in files.
152      * @param publicId public ID in dtd
153      * @param systemId system ID in dtd
154      * @return always null
155      * @throws SAXException generated by chained EntityResolver
156      * @throws IOException generated by chained EntityResolver
157      */
158     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
159     {
160         // log dtd info (not entities)
161         if (systemId.indexOf(".dtd") != -1)
162         {
163             // "-//W3C//DTD XHTML 1.0 Transitional//EN"
164             String name = publicId;
165 
166             if (name != null)
167             {
168                 int start = name.indexOf("-//W3C//DTD ");
169                 int end = name.lastIndexOf("//EN");
170 
171                 if (start != -1 && end > (start + 12))
172                 {
173                     // DTD "friendly" name
174                     name = name.substring(start + 12, end);
175                 }
176 
177             }
178 
179             // write a "dtd" element to output
180             Element dtd = new DefaultElement("dtd");
181             dtd.addAttribute("publicId", publicId);
182             dtd.addAttribute("systemId", systemId);
183             dtd.addAttribute("display", name);
184             writeToLog(dtd);
185         }
186 
187         return chainedEntityResolver.resolveEntity(publicId, systemId);
188     }
189 
190     /***
191      * write an element to the xml log file.
192      * @param element Element to write
193      */
194     private void writeToLog(Element element)
195     {
196         try
197         {
198             this.out.write(element);
199         }
200         catch (IOException e)
201         {
202             // ignore
203         }
204     }
205 }